Understanding By Example

Functions:

1
# Function Context Cheatsheet
2
​
3
## Types of Invocation
4
- Applies to only **named** and **unnamed** functions
5
- **Doesn't matter** for fat arrow functions
6
​
7
### Function-style invocation
8
- Context of the function will be global context **UNLESS** binded
9
​
10
### Method-style invocation
11
- Context of the function will be the object which the function is called on **UNLESS** binded
12
​
13
```javascript
14
const obj = {
15
name: 'Example Object',
16
unnamedFunc: function() {
17
console.log(this.name);
18
}
19
};
20
​
21
// Method-style invocation
22
obj.unnamedFunc(); // 'Example Object'
23
​
24
// Function-style invocation
25
const unnamedFunc = obj.unnamedFunc;
26
unnamedFunc(); // Global context
Copied!

Types of Functions

Named Function

    explicit return keyword required
    curly braces {} around function body
    NOT saved to a variable
    parameters must be surrounded by parentheses ()
    context is defined by how it's invoked or called
      function-style: global context
      method-style: context is object that function is being called on
    calling bind on the function will return a function binded to the context of the bind argument
1
function namedFunc(params) {
2
return 'named function'
3
}
Copied!
1
// bindedNamedFunc will have the context of obj
2
const bindedNamedFunc = namedFunc.bind(obj);
Copied!

Unnamed Function

    explicit return keyword required
    curly braces {} around function body
    MUST be saved to a variable
    parameters must be surrounded by parentheses ()
    context is defined by how it's invoked or called
      function-style: global context
      method-style: context is object that function is being called on
    calling bind on the function will return a function binded to the context of the bind argument
1
const unnamedFunc = function(params) {
2
return 'unnamed function'
3
}
Copied!
1
// bindedUnnamedFunc will have the context of obj
2
const bindedUnnamedFunc = unnamedFunc.bind(obj);
Copied!

Explicit Fat Arrow Function

    explicit return keyword required
    curly braces {} around function body
    MUST be saved to a variable
    parameters must be surrounded by parentheses () IF more than one parameter
    takes the context of where it's defined
    CANNOT be binded using bind
1
const explicitFatArrow = params => {
2
return 'explicit fat arrow function'
3
};
Copied!

Implicit Fat Arrow Function

    NO return keyword
    function body can only consist of what is being returned
    Optional parentheses () around function body
    NOTE: Parentheses needs to be used if returning an object ex: ({ key: value })
    MUST be saved to a variable
    parameters must be surrounded by parentheses () IF more than one parameter
    takes the context of where it's defined
    CANNOT be binded using bind
1
const implicitFatArrow = (params) => 'implicit fat arrow function';
Copied!
1
const implicitFatArrow = (params) => ('implicit fat arrow function');
Copied!
1
const implicitFatArrow = (params) => ({
2
function: 'implicit fat arrow'
3
});
Copied!

Bind

    bind accepts multiple arguments
    first argument is the context that you want to bind the function to
    any arguments that come afterwards will be passed in when the bound function is called BEFORE the call time arguments
    ```
1
// Arrow Functions
2
// 1. Syntax
3
// 2. Scoping with Arrow Functions
4
​
5
function logger(title, body) {
6
console.log("\x1b[31m%s\x1b[0m", title);
7
console.log(' ', body);
8
}
9
​
10
// Named Function
11
function sayHelloNamed(name) {
12
return 'hello ' + name;
13
}
14
​
15
logger('Named Function', sayHelloNamed('Justin'));
16
​
17
// Unnamed Function
18
const sayHelloUnnamed = function(name) {
19
return 'hello ' + name;
20
};
21
​
22
logger('Unnamed Function', sayHelloUnnamed('Soon-Mi'));
23
​
24
​
25
​
26
​
27
​
28
​
29
​
30
// Fat Arrow Function with EXPLICIT return
31
// curly braces around body of fat arrow functions need explicit return keyword
32
// const sayHelloExplicit = (name) => {
33
// return 'hello ' + name;
34
// };
35
​
36
// No parentheses surrounding parameter needed if ONLY one parameter
37
const sayHelloExplicit = name => {
38
return 'hello ' + name;
39
};
40
​
41
logger('Fat Arrow Function with Explicit Return', sayHelloExplicit('Gordon'));
42
​
43
​
44
​
45
​
46
​
47
​
48
​
49
​
50
​
51
​
52
​
53
​
54
// Fat Arrow Function with IMPLICIT return
55
// Also called a One-Liner Fat Arrow function
56
// should only use this when the function's body is NOT multi-line
57
const sayHelloImplicit = (name) => 'hello' + name;
58
​
59
// can use parentheses around function body as well
60
// const sayHelloImplicit = (name) => ({
61
// hello: 'Angela'
62
// });
63
​
64
// notice the semicolon ; at the end
65
​
66
logger('Fat Arrow Function with Implicit Return', sayHelloImplicit('Angela'));
67
​
68
​
69
​
70
​
71
​
72
​
73
console.log('\n--------------\n');
74
​
75
​
76
​
77
​
78
// Example using fat arrow functions
79
const arr = [1, 2, 3];
80
​
81
const newArr = arr.map(el => {
82
return el + 2;
83
});
84
// const newArr = arr.map(function(el) {
85
// return el + 2;
86
// });
87
​
88
logger('Original Array, `arr`', arr);
89
logger('New Mapped Array, `newArr`', newArr);
90
​
91
​
92
​
93
​
94
console.log('\n--------------\n');
95
​
96
​
97
​
98
​
99
​
100
​
101
// Context using Fat Arrow functions
102
const pony = {
103
name: 'Lucy',
104
wrappedSayName: function() {
105
console.log(this.name);
106
return function() {
107
console.log(this.name);
108
console.log('Hello my name is ' + this.name);
109
}
110
},
111
wrappedArrowSayName: function() {
112
console.log(this.name);
113
return () => {
114
console.log('Hello my name is ' + this.name);
115
}
116
}
117
};
118
​
119
pony.wrappedSayName = pony.wrappedSayName.bind(pony);
120
let wrap = pony.wrappedSayName().bind(pony); // method-style invocation
121
wrap(); // function-style invocation
122
​
123
console.log('-----------');
124
​
125
wrap = pony.wrappedArrowSayName(); // method-style invocation
126
wrap();
127
​
128
console.log('-----------');
129
​
130
const arrowSayName = pony.wrappedArrowSayName; // not invoking
131
wrap = arrowSayName(); // function-style invocation
132
wrap();
133
​
134
​
135
​
136
// bound to the context of wherever it's defined
137
​
138
​
139
​
140
​
141
​
142
​
143
console.log('-----------');
144
​
145
const zoomMeeting = {
146
students: ['Christian', 'Ronald','Wren'],
147
listStudent: function(studentName) {
148
console.log(this.students);
149
// console.log(studentName);
150
},
151
listStudents: function() {
152
const listStudent = this.listStudent;
153
listStudent(); // function-style
154
console.log('***');
155
this.students.forEach(listStudent);
156
}
157
};
158
​
159
zoomMeeting.listStudents();
Copied!

Scope:

1
// Global Scope
2
​
3
let cities = ["NYC", "SF"];
4
​
5
//console.log(cities);
6
​
7
​
8
​
9
​
10
// Local / Function Scope
11
​
12
​
13
function sayThings() {
14
// let cities = ['Bogota', 'Madrid'];
15
// console.log(cities);
16
​
17
let word = 'dinosaur';
18
console.log(word);
19
}
20
​
21
// console.log(cities); // prints NYC & SF
22
// console.log(word); // ReferenceError
23
//sayThings();
24
​
25
​
26
​
27
​
28
​
29
​
30
​
31
​
32
​
33
​
34
// Block Scope
35
​
36
if (true) {
37
let cats = ['Roma', 'Luigi'];
38
//console.log(cats); // prints Roma & Luigi
39
}
40
​
41
//console.log(cats) // ReferenceError
42
​
43
// This example was extended to show how scope within nested blocks works
44
// As Justin pointed out, it also leads directly into closures
45
​
46
let carrot = 'snake';
47
​
48
if (true){
49
let carrot = 'doggie!';
50
//console.log(carrot);
51
if (true) {
52
carrot = 'carrot';
53
console.log(carrot); // prints carrot
54
}
55
for(let i = 1; i < 5; i++){
56
console.log(`i is ${i}`);
57
};
58
//console.log(`i is ${i}`); // reference error
59
console.log("line 57:" ,'george' ,carrot);
60
}
61
​
62
console.log(carrot); // prints snake
Copied!

Closure

1
// Closure
2
// When an inner function uses, or changes,
3
// variables defined in an outer scope.
4
// NOT for declaring a variable of the same name in an inner scope.
5
function sayHi() {
6
let name = 'Bryan Guner';
7
​
8
function greeting() {
9
// here greeting function closes over, or captures, the name variable
10
// to read it's value
11
return "Hi there, " + name + "!";
12
}
13
// Here, we return the return value of the greeting function
14
return greeting();
15
}
16
// console.log(sayHi());
17
function nameAndCity() {
18
let person = {
19
name: 'Sergey',
20
city: 'Moscow'
21
};
22
​
23
function changeCity() {
24
// here changeCity function closes over the person variable
25
// and reassigns a value on an existing key
26
person.city = 'Toronto';
27
}
28
changeCity();
29
// the person variable will show the changes from the changeCity function
30
return person;
31
}
32
// console.log(nameAndCity());
33
function smoothieMaker() {
34
let ingredients = [];
35
​
36
function addIngredient( ingredient ) {
37
// Here addIngredient function closes over the ingredients variable
38
// to push new elements into the ingredients variable.
39
// We have created a private state where we cannot access
40
// the ingredients array from the outside and can only access
41
// the variable from the inner function.
42
ingredients.push( ingredient );
43
return ingredients;
44
}
45
// Here the return value for smoothiemaker is the return value
46
// is the function addIngredient, NOT addIngredient's return value
47
return addIngredient;
48
}
49
// Here we initialize we return a new addIngredient function
50
// which has closed over the ingredients array
51
const makeSmoothie = smoothieMaker();
52
console.log( makeSmoothie );
53
console.log( makeSmoothie( 'spinach' ) ); // prints [ spinach ]
54
console.log( makeSmoothie( 'turmeric' ) ); // prints [ spinach, turmeric ]
55
// let mySmoothie = makeSmoothie();
56
// Here we return a new and different addIngredient function
57
// which has closed over a new a different ingredients array
58
const makeSmoothie2 = smoothieMaker();
59
console.log( makeSmoothie2( 'kale' ) ); // prints [ kale ] -- does not include spinach and turmeric
60
function createCounter() {
61
let count = 0;
62
return function () {
63
count++;
64
return count;
65
}
66
}
67
let counter1 = createCounter();
68
let counter2 = createCounter();
69
// console.log(counter1());
70
// console.log(counter1());
71
// console.log(counter1());
72
// console.log(counter1());
73
// What will this print out?
74
// console.log(counter2());
75
// Brief talk of scope and redeclaring a const variable in a loop
76
for ( let i = 0; i < 5; i++ ) {
77
const num = i + 2;
78
}
79
​
80
​
81
// In the following examples we will predict what will
82
// be printed to the terminal
83
​
84
​
85
​
86
​
87
​
88
​
89
// 1
90
​
91
function dinerBreakfast(food) {
92
let order = "I'd like cheesy scrambled eggs and ";
93
​
94
function finishOrder() {
95
return order + food;
96
}
97
​
98
return finishOrder();
99
}
100
​
101
// console.log(dinerBreakfast('green tea'));
102
​
103
​
104
​
105
​
106
​
107
​
108
​
109
​
110
​
111
// 2
112
​
113
function dinerBreakfast2(food) {
114
let order = "I'd like a(n) " + food;
115
​
116
function withEggs() {
117
order = order + ' and cheesy scrambled eggs, please!'
118
};
119
​
120
withEggs();
121
return order;
122
}
123
​
124
// console.log(dinerBreakfast2('avocado toast'));
125
​
126
​
127
​
128
​
129
​
130
​
131
​
132
​
133
​
134
// 3
135
​
136
function dinerBreakfast3() {
137
let order = "I'd like cheesy scrambled eggs";
138
​
139
return function (food) {
140
order = order + " and " + food;
141
return order;
142
}
143
}
144
​
145
let breakfastOrder = dinerBreakfast3();
146
​
147
console.log(breakfastOrder);
148
console.log(breakfastOrder('cappuccino'));
149
console.log(breakfastOrder('pancakes'));
Copied!

Context:

1
// In the following examples we will predict what will
2
// be printed to the terminal
3
​
4
​
5
function whatIsThis() {
6
console.log(this);
7
}
8
​
9
const pony = {
10
name: "Lucy",
11
whatIsThis: function () {
12
console.log(this);
13
},
14
sayName: function () {
15
console.log('Hello my name is ' + this.name);
16
},
17
changeName: function (newName) {
18
this.name = newName;
19
this.sayName();
20
}
21
}
22
​
23
​
24
// 1.
25
// whatIsThis();
26
​
27
​
28
// 2.
29
// pony.whatIsThis();
30
​
31
​
32
// 3.
33
// pony.sayName();
34
​
35
​
36
// 4.
37
// pony.changeName("Layla");
38
​
39
​
40
// 5.
41
// const sayNameFunc = pony.sayName;
42
// sayNameFunc();
43
​
44
​
45
// 6.
46
// const boundSayName = pony.sayName.bind(pony);
47
// boundSayName();
48
​
49
​
50
// 7.
51
const bart = {
52
name: 'Bart'
53
}
54
​
55
const boundToBart = pony.sayName.bind(bart);
56
// boundToBart();
57
​
58
​
59
// 8.
60
const changeBartsName = pony.changeName.bind(bart);
61
changeBartsName('Sergey');
62
​
63
​
64
// Context
65
// What does the keyword 'this' refer to?
66
// The context is determined by HOW a function is invoked
67
​
68
​
69
// Different ways of invoking a function
70
// function style
71
// context is set to the global object
72
// 'this' refers to the global object
73
// method style
74
// context is set to the object on which the method is called
75
// 'this' refers to the object on which the method is called
76
​
77
​
78
// How to ensure bind never change the context of a function
79
// no matter how it is invoked.
80
// .bind()
81
// By adding .bind() to the end of a function we set the context
82
// to equal the argument passed to .bind()
83
// 'this' will refer to the argument passed to .bind()
84
​
85
​
86
// Scope VS Context
87
// VERY DIFFERENT THINGS!!
88
​
89
// Scope:
90
// Availability of variables at a line in your application
91
// Context:
92
// The value of this
93
// Determined by how a function has been invoked or the .bind() method
94
​
95
​
96
​
97
​
98
const cat = {
99
name: 'Luigi',
100
age: 2,
101
whatIsThis: function () {
102
console.log(this);
103
},
104
nameAndAge: function () {
105
console.log(this.name + " is " + this.age + " years old.")
106
}
107
};
108
​
109
// cat.whatIsThis();
110
// cat.nameAndAge();
111
​
112
const nameAndAgeFunc = cat.nameAndAge;
113
nameAndAgeFunc();
114
​
115
const boundNameAndAge = cat.nameAndAge.bind(cat);
116
// boundNameAndAge();
117
​
118
​
119
​
120
​
121
​
122
​
123
​
124
​
125
const cat2 = {
126
name: 'Roma',
127
age: 3
128
}
129
​
130
function nameAndAge() {
131
console.log(this.name + " is " + this.age + " years old.");
132
}
133
​
134
const dog = {
135
name: 'Napo',
136
age: 5
137
}
138
​
139
const catNameAge = nameAndAge.bind(cat2);
140
const dogNameAge = nameAndAge.bind(dog);
141
​
142
catNameAge();
143
dogNameAge();
144
​
145
​
146
​
147
​
148
​
149
const obj = {
150
name: 'Example Object',
151
unnamedFunc: function() {
152
console.log(this.name);
153
}
154
};
155
​
156
// Method-style invocation
157
obj.unnamedFunc(); // 'Example Object'
158
​
159
// Function-style invocation
160
const unnamedFunc = obj.unnamedFunc;
161
unnamedFunc(); // `undefined` because Global context
162
​
163
​
164
​
165
​
166
​
167
console.log('-------------------');
168
​
169
​
170
​
171
​
172
​
173
​
174
// Unnamed Func
175
const dog = {
176
name: 'Digby'
177
};
178
​
179
const boundFunc = obj.unnamedFunc.bind(dog);
180
boundFunc(); // Digby
181
obj.unnamedFunc(); // Example Object
182
​
183
​
184
​
185
​
186
​
187
​
188
​
189
console.log('-------------------');
190
​
191
​
192
​
193
​
194
// Bind Time and Call Time Arguments
195
// bind time arguments passed in first, then call time arguments
196
function printAge(...args) {
197
const age = args[0];
198
const year = args[1];
199
console.log(args);
200
console.log(this.name + ' is ' + age + ' years old. Born in ' + year);
201
}
202
​
203
const otherArgs = [2005];
204
​
205
const printDigby = printAge.bind(dog, 12, ...otherArgs);
206
printDigby(2000);
207
printDigby(2008);
208
​
209
// const printRealDigby = printAge.bind(dog, 4);
210
// printRealDigby(2002);
Copied!
Last modified 1mo ago